package logic

import (
	"context"
	"database/sql"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"im_sys/apps/social/socialmodels"
	"im_sys/pkg/constants"
	"im_sys/pkg/xerr"
	"time"

	"im_sys/apps/social/rpc/internal/svc"
	"im_sys/apps/social/rpc/social"

	"github.com/zeromicro/go-zero/core/logx"
)

type FriendPutInHandleLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

var (
	ErrFriendReqBeforePass   = xerr.NewErr("好友申请已通过")
	ErrFriendReqBeforeRefuse = xerr.NewErr("好友申请已拒绝")
)

func NewFriendPutInHandleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FriendPutInHandleLogic {
	return &FriendPutInHandleLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *FriendPutInHandleLogic) FriendPutInHandle(in *social.FriendPutInHandleReq) (*social.FriendPutInHandleResp, error) {
	// todo: add your logic here and delete this line
	// 1. 获取好友申请记录
	friendReq, err := l.svcCtx.FriendRequests.FindOne(l.ctx, uint64(in.FriendReqId))

	if err != nil && !errors.Is(err, socialmodels.ErrNotFound) {
		return nil, errors.Wrapf(xerr.NewDBErr(), "find friend request by friend reqid failed: %v", err)
	}

	// 2. 验证是否处理
	switch constants.HandlerResult(friendReq.HandleResult.Int64) {
	case constants.PassHandlerResult:
		return nil, ErrFriendReqBeforePass
	case constants.RejectHandlerResult:
		return nil, ErrFriendReqBeforeRefuse
	default:
	}

	// 3. 更新好友关系（使用事务操作两张表，修改好友申请表，在好友表新增）
	friendReq.HandleResult.Int64 = int64(in.HandleResult) // 要更新的字段
	if err := l.svcCtx.FriendRequests.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		if err := l.svcCtx.FriendRequests.UpdateWithTrx(ctx, session, friendReq); err != nil {
			return errors.Wrapf(xerr.NewDBErr(), "update friend request failed: %v", err)
		}

		// 对方拒绝了好友申请
		if constants.HandlerResult(in.HandleResult) == constants.RejectHandlerResult {
			return nil
		}

		// 新增好友关系
		friends := []*socialmodels.Friends{
			{
				UserId:    friendReq.UserId,
				FriendUid: friendReq.ReqUid,
				CreatedAt: sql.NullTime{
					Time:  time.Now(),
					Valid: true,
				},
			},
			{
				UserId:    friendReq.ReqUid,
				FriendUid: friendReq.UserId,
				CreatedAt: sql.NullTime{
					Time:  time.Now(),
					Valid: true,
				},
			},
		}
		if _, err := l.svcCtx.Friends.InsertsWithTrx(ctx, session, friends...); err != nil {
			return errors.Wrapf(xerr.NewDBErr(), "insert friends failed: %v", err)
		}
		return nil
	}); err != nil {
		return nil, err
	}
	return &social.FriendPutInHandleResp{}, nil
}
